Skip to content

How to use GitLab CI in Docker

TLDR

  • GitLab Installation Advice: Always set external_url to ensure SSH and HTTP links are correct. If using a non-standard port, you must also set nginx['listen_port'].
  • Volume Mounting: It is recommended to use a Docker Volume instead of a Bind Mount for GitLab's /var/opt/gitlab to prevent the artifacts feature from failing due to insufficient permissions.
  • Runner Registration: If the GitLab URL is 127.0.0.1 or localhost, you must manually specify the clone_url during registration; otherwise, the Runner will be unable to connect.
  • Docker Executor Permissions: If you need to execute Docker commands within CI, you must mount /var/run/docker.sock to the Runner and set privileged to true in config.toml.
  • Network Mode: The Runner's network_mode should not be set to host. It is recommended to use gitlab_default to ensure the Runner can communicate with the GitLab container properly.
  • CI Variable Limitations: Docker Image names only support lowercase. If the project name contains uppercase letters, please use the $CI_PROJECT_PATH_SLUG variable.

Installing GitLab on Docker

When deploying GitLab in a Docker environment, the accuracy of the configuration file is critical.

Key Settings and Precautions

  • When will you encounter issues?: If external_url is not set correctly, the SSH and HTTP repository links generated by GitLab will be invalid or appear as garbled text.
  • Solution:
    • Explicitly specify external_url in the GITLAB_OMNIBUS_CONFIG of docker-compose.yml.
    • If using a port other than 80, you must simultaneously set nginx['listen_port'].
    • Avoid using Bind Mounts for /var/opt/gitlab; use a Docker Volume instead to resolve permission issues with the artifacts feature.
    • If an "invalid port specification" error occurs, wrap the port mapping (e.g., 5022:22) in quotes.
yaml
# docker-compose.yml example snippet
environment:
  GITLAB_OMNIBUS_CONFIG: |
    external_url 'http://127.0.0.1:5080/'
    nginx['listen_port'] = 80
    gitlab_rails['gitlab_shell_ssh_port'] = 5022
ports:
  - "5080:80"
  - "5022:22"

Installing and Registering GitLab Runner on Docker

The Runner configuration determines whether CI/CD tasks can be executed successfully.

Registration and Configuration Highlights

  • When will you encounter issues?: When the GitLab container uses 127.0.0.1 or localhost as the URL, the Runner will be unable to pull code after registration because it cannot resolve the address.
  • Solution:
    • After registration, edit config.toml and manually add a clone_url pointing to the correct IP of the GitLab container.
    • If you need to execute Docker commands (e.g., docker build), you must mount docker.sock.
toml
# config.toml configuration example
[[runners]]
  url = "http://172.20.0.2"
  clone_url = "http://172.20.0.2"
  executor = "docker"
  [runners.docker]
    privileged = true
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    network_mode = "gitlab_default"

WARNING

Do not set network_mode to host, as this may cause the GitLab service to respond abnormally.


GitLab CI Example: .NET 6 Project

Define Build, List, and Deploy stages via .gitlab-ci.yml to implement an automated workflow.

Core Implementation Details

  • When will you encounter issues?: When outputting file paths in list-job, if the file name contains Chinese characters, it will be translated due to encoding issues.
  • Solution: Use git config --global core.quotepath false to disable special character translation.
  • Deployment Precautions: Since Docker Image names only support lowercase, please use the $CI_PROJECT_PATH_SLUG variable to dynamically generate the Image name.
yaml
# .gitlab-ci.yml example snippet
deploy-job:
  stage: deploy
  script:
    - cd build
    - docker build --tag $CI_PROJECT_PATH_SLUG:latest .
    - docker stop $CI_PROJECT_NAME || true && docker rm $CI_PROJECT_NAME || true
    - docker run -d -p 9080:80 --name $CI_PROJECT_NAME $CI_PROJECT_PATH_SLUG:latest

Summary

By enabling the Runner's privileged permission and mounting docker.sock, you allow the Runner to directly call the host's Docker Engine for containerized deployment. This is the most suitable approach for CI/CD in a single-node Docker environment.


Change Log

  • 2022-10-24 Initial documentation created.